﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WMPLib;
using System.Windows.Forms;

namespace Altbrot.Yawr.Player
{
    public delegate void PlayerStatusChangedEventHandler(string status);

    public class WMPLibPlayer : IStreamPlayer, IDisposable
    {
        public event PlayerStatusChangedEventHandler OnStatusTextChanged;
        public event MethodInvoker OnMediaChanged;
        private WMPLib.WindowsMediaPlayer _player;
        private Uri _currentUri;
        private string _currentMediaName;
        private Timer _timer;
        private Form _form;

        public WMPLibPlayer(Form form)
        {
            _player = new WMPLib.WindowsMediaPlayer();
            _player.PlayStateChange += new WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(_player_PlayStateChange);
            _timer = new Timer();
            _timer.Interval = 1000;
            _timer.Tick += new EventHandler(_timer_Tick);
            _form = form;
        }

        public WMPLibPlayer()
        {
            _player = new WMPLib.WindowsMediaPlayer();
            _player.PlayStateChange += new WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(_player_PlayStateChange);
            _timer = new Timer();
            _timer.Interval = 1000;
            _timer.Tick += new EventHandler(_timer_Tick);
        }

        public StreamPlayerPlayState PlayerState 
        {
            get
            {
                return (StreamPlayerPlayState)
                    Enum.Parse(typeof(StreamPlayerPlayState), _player.playState.ToString());
            }
        }

        public string MediaName
        {
            get
            {
                if (_player != null && _player.currentMedia != null)
                {
                    return _player.currentMedia.name;
                }
                return string.Empty;
            }
        }

        public string MediaBitrate
        {
            get
            {
                if (_player != null && _player.currentMedia != null)
                {
                    string bitrate = _player.currentMedia.getItemInfo("Bitrate");
                    int calcbitrate;
                    if (Int32.TryParse(bitrate, out calcbitrate))
                    {
                        return (calcbitrate / 1000).ToString();
                    }
                }
                return string.Empty;
            }
        }

        #region public methods

        public void Play(Uri url)
        {
            if (url != null)
            {
                if (PlayerState != StreamPlayerPlayState.wmppsPlaying || !url.Equals(_currentUri))
                {
                    _player.URL = url.AbsoluteUri;
                    _player.controls.play();
                    _currentUri = url;                                        
                }
            }
        }

        public void Stop()
        {            
            _player.controls.stop();
        }

        public void Pause()
        {
            _player.controls.pause();
        }

        #endregion

        #region private

        void _timer_Tick(object sender, EventArgs e)
        {
            if (_form != null && PlayerState == StreamPlayerPlayState.wmppsPlaying && _currentMediaName != _player.currentMedia.name)
            {
                _currentMediaName = _player.currentMedia.name;
                this._form.Invoke(OnMediaChanged);
            }
        }

        private void FireOnStatusTextChanged(string message)
        {
            if (OnStatusTextChanged != null)
                OnStatusTextChanged(message);
        }

        #endregion

        #region event handlers

        private void _player_PlayStateChange(int NewState)
        {
            if (this.OnStatusTextChanged != null)
            {
                switch (NewState)
                {
                    // playing
                    case 3:                        
                        this.FireOnStatusTextChanged(_player.currentMedia.name);
                        _currentMediaName = _player.currentMedia.name;
                        _timer.Start();
                        break;

                    // buffering
                    case 6:
                        this.FireOnStatusTextChanged("Buffering...");
                        break;

                    // reconnecting to stream
                    case 11:
                        this.FireOnStatusTextChanged("Reconnecting to Stream...");
                        break;

                    // stopped
                    case 1:
                        _timer.Stop();
                        break;
                    // paused
                    case 2:
                    // fast forward
                    case 4:
                    // fast rewind
                    case 5:
                    // waiting - connection established, but server not sending data. 
                    //Waiting for session to begin
                    case 7:
                    // end - media ended, media item has completed playback
                    case 8:                        
                    // transitioning - preparing new media item
                    case 9:
                    // ready to begin playing
                    case 10:
                        this.FireOnStatusTextChanged(string.Empty);
                        break;
                    default:
                        break;
                } 
            }
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            _player.close();
        }

        #endregion
    }
}
